package parserdecoder

import (
	"bufio"
	"io"
	"iptv_server/v3/v2_src/utils"
	"iptv_server/v3/v2_src/utils/common"
	"iptv_server/v3/v2_src/utils/orderedmap"
	"strings"
)

func NewParserM3U(sorter common.Sorter, filter common.Filter, mapper common.Mapper) Parser {
	m := &M3U{
		sorter: sorter,
		filter: filter,
		mapper: mapper,
	}
	return m
}

type info struct {
	id                     string
	groupName, channelName string
}

/*
//#EXTINF:<duration时长秒(-1=未知)>,<optional_title> <parameter1>=<value1> <parameter2>=<value2> ...
//<media_file_url>
//
// tvg-id: 用于标识电视节目（例如 IPTV 中的频道 ID）。
// tvg-name: 节目源名称。
// tvg-logo: 节目源的图标 URL。
// group-title: 频道组标题（例如新闻组、电影组等）。
// tvg-url: 频道的官网或来源 URL。
*/

// #EXTINF:-1,tvg-id="cctv8" tvg-name="cctv8" tvg-logo="https://epg.v1.mk/logo/cctv8.png" group-title="央视",CCTV-8 高清名字可以有空格

func trim(v string) string {
	return strings.Trim(v, " ,")
}

func getM3U_info(str string) *info {
	runes := []rune(str)
	if len(runes) == 0 {
		return nil
	}

	kv := make(map[string]string)

	quote := false // "
	equal := false // =

	key := ""
	value := []rune("")
	namesX := make([]string, 0)

	duration := "" // #EXTINF:-1  //秒

	// byte 操作 导致了 utf-8 编码问题
	for i := 0; i < len(runes); i++ {
		c := runes[i]
		switch c {
		case '"':
			quote = !quote
			if !quote { //闭合, 只有v才会被""包围
				if len(key) > 0 && len(value) > 0 {
					kv[strings.ToLower(key)] = string(value)
				}
				key = ""
				value = []rune("")
				equal = false
			}

		case '=':
			if quote {
				value = append(value, c)
			} else {
				equal = true
				key = string(value)
				value = []rune("")
			}
		case ' ':
			if quote || len(key) == 0 {
				// if len(value) > 25 {
				// 	// value 最多长度 25
				// 	continue
				// }
				if len(value) > 0 {
					// 空格只有在 引号中间, value中间(不能作为value的开头).
					value = append(value, c)
				}
				continue
			}
			fallthrough
		case ',':
			if quote {
				value = append(value, c)
			} else if len(key) == 0 {
				// 无key
				if len(value) > 0 {
					v := trim(string(value))
					if len(duration) == 0 {
						duration = v
					} else {
						//// 这个value 可能为 name
						// kv[strings.ToLower(string(value))] = "true"
						namesX = append(namesX, v)
					}
				}
			} else {
				// 有key 加入 kv
				var v string
				if len(value) == 0 {
					v = "?"
				} else {
					v = trim(string(value))
				}

				key = trim(key)
				kv[strings.ToLower(key)] = v
				key = ""
				value = []rune("")
				equal = false
			}

		default:
			value = append(value, c)
		}
	}

	if ds := strings.Split(duration, ":"); len(ds) > 1 {
		// duration := "" // #EXTINF:-1
		// 单位 秒
		duration = ds[1]
	} else {
		duration = "-1"
	}
	_ = duration

	name := ""

	key = strings.ToLower(trim(key))
	v := trim(string(value))
	if len(v) > 0 {
		if len(key) > 0 {
			// kv
			kv[key] = v
		} else if !equal {
			// name, 优先最右的为name
			name = v
			// namesX = append(namesX, name)
		}
	}

	if len(name) == 0 {
		for i := len(namesX) - 1; i >= 0; i-- {
			name = namesX[i]
			if len(name) > 0 {
				break
			}
		}
	}

	//大分组
	group := kv["group-title"]
	if len(group) == 0 {
		// group = kv["tvg-name"]
		// if len(group) == 0 {
		group = UNDEFINED
		// }
	}

	//频道源
	// tvg-id
	// tvg-name tvg-logo
	id := kv["tvg-id"]
	if len(id) == 0 {
		id = kv["tvg-name"]
	}

	if len(id) == 0 {
		id = name
		if len(id) == 0 {
			id = UNDEFINED
		}
	}

	if len(name) == 0 {
		// id 默认值 == "? ? ? ?"
		name = id
	}

	inf := &info{
		id:          strings.ToLower(id),
		groupName:   strings.ToLower(group),
		channelName: name,
	}
	return inf
}

type M3U struct {
	sorter common.Sorter
	filter common.Filter
	mapper common.Mapper
}

func (m *M3U) Parse(reader io.Reader) (*kkv, error) {
	// kvs := make(map[string]map[string][]string)
	bufferedReader := bufio.NewReader(reader)

	// bs, err := bufferedReader.Peek(100)
	// if err != nil {

	// }

	// "#extinf:"
	// #EXTM3U

	kvs := new_kkv()

	var inf *info
	count := 0
	//url
	var group *orderedmap.Orderedmap[[]NameUrl]
	var channelLines []NameUrl
	isM3U := false
	for {
		line, err := bufferedReader.ReadString('\n')
		if err != nil {
			break
		}

		count++
		if count >= 100 && !isM3U {
			// 100 行了都没发现 m3u 特征, 则 返回
			break
		}
		if len(line) > 1024*1024 || count > 100*1024 {
			//  1行最多 1M; >则视为 异常文件
			//  最多10万行
			break
		}

		line = strings.Trim(line, "\n\r ")
		line = strings.TrimSpace(line)
		if len(line) == 0 {
			continue
		}

		//
		if line[0] == '#' {
			if len(line) < 10 {
				continue
			}
			pre := strings.ToLower(line[:10])
			//  #EXTINF:
			if strings.HasPrefix(pre, "#extinf:") {
				// info
				isM3U = true
				inf = getM3U_info(line)
			}
			continue
		} else if utils.IsHttpUrl(line) {
			// url
			if inf == nil {
				continue
			}

			if v, ok := kvs.Get(inf.groupName); ok {
				group = v
			} else {
				group = orderedmap.New[[]NameUrl]()
				kvs.Set(inf.groupName, group)
			}

			if v, ok := group.Get(inf.id); ok {
				channelLines = v
			} else {
				channelLines = make([]NameUrl, 0, 10)
				group.Set(inf.id, channelLines)
			}

			found := false
			for _, l := range channelLines {
				if l.url == line {
					found = true
					break
				}
			}

			if !found {
				channelLines = append(channelLines, NameUrl{
					name: inf.channelName,
					url:  line,
				})
				group.Set(inf.id, channelLines)
			}
			inf = nil
		}
	}

	kvs = withMapper(kvs, m.mapper)
	kvs = withSorterAndFilter(kvs, m.sorter, m.filter)
	return kvs, nil
}
